package com.otogami.mediamarkt.robots;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.otogami.core.Robot;
import com.otogami.core.model.Platform;
import com.otogami.core.model.Videogame;
import com.otogami.mediamarkt.MediamarktConnector;

/**
 * Class responsible for scraping the Mediamarkt website in a multi-threaded way.
 * 
 * @author islomar
 * 
 */
public class MediamarktConcurrentRobot implements Robot {

	private static Logger logger = LoggerFactory.getLogger(MediamarktConcurrentRobot.class);
	
	private long startTime;
	
	
	public Collection<Videogame> getVideogamesOnPlatform(Platform platform) {
		startTime = System.currentTimeMillis();
		Set<Videogame> videogameList = new HashSet<Videogame>();

		int totalNumberOfPages = getTotalNumberOfPages(platform);
		
        ExecutorService executor = Executors.newFixedThreadPool(totalNumberOfPages);
        for (int pageNumber = 1; pageNumber <= totalNumberOfPages; pageNumber++) {
            Runnable worker = new MediamarktWorkerThread(pageNumber, videogameList, new MediamarktConnector(platform));
            executor.execute(worker);
          }
        executor.shutdown();
        waitWhileAllThreadsAreFinished(executor);
        
        logger.info("Finished all threads");
        logger.info("Total number of videogames parsed for platform " + platform + ": " + videogameList.size());
        logger.info("Total time elapsed in seconds: " + getElapsedTime());
        return videogameList;
	}

	private int getTotalNumberOfPages(Platform platform) {
		
		MediamarktConnector mediamarktConnector = new MediamarktConnector(platform);
		int totalNumberOfPages = mediamarktConnector.getTotalNumberOfPages();
		logger.info("Total number of threads to be run in parallel (one for each page to scrape): " + totalNumberOfPages);
		return totalNumberOfPages;
	}

	private void waitWhileAllThreadsAreFinished(ExecutorService executor) {
		while (!executor.isTerminated()) {
        }
	}
	
    public double getElapsedTime() {
        long endTime = System.currentTimeMillis();
        return (double) (endTime - startTime) / (1000);
    }

}
